{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020/09/08, 20:18:04, Iteration: 100, Train Loss: 1.0815e+00, c: 7.8072e-01, d: 3.0074e-01, s: 5.9275e-01, l1_reg: 6.3135e+02, l2_reg: 9.9812e+01\n",
      "2020/09/08, 20:18:05, Iteration: 200, Train Loss: 3.2009e-01, c: 1.9414e-01, d: 1.2594e-01, s: 6.7021e-01, l1_reg: 6.2222e+02, l2_reg: 9.7402e+01\n",
      "2020/09/08, 20:18:05, Iteration: 300, Train Loss: 1.7976e-01, c: 8.3516e-02, d: 9.6236e-02, s: 6.3948e-01, l1_reg: 6.2106e+02, l2_reg: 9.7059e+01\n",
      "2020/09/08, 20:18:06, Iteration: 400, Train Loss: 1.4393e-01, c: 7.5765e-02, d: 6.8154e-02, s: 6.1879e-01, l1_reg: 6.2096e+02, l2_reg: 9.6974e+01\n",
      "2020/09/08, 20:18:07, Iteration: 500, Train Loss: 9.7564e-02, c: 7.2228e-02, d: 2.5329e-02, s: 5.8426e-01, l1_reg: 6.2166e+02, l2_reg: 9.7100e+01\n",
      "2020/09/08, 20:18:08, Iteration: 600, Train Loss: 2.0463e-01, c: 1.9216e-01, d: 1.2459e-02, s: 5.7385e-01, l1_reg: 6.2145e+02, l2_reg: 9.6996e+01\n",
      "2020/09/08, 20:18:08, Iteration: 700, Train Loss: 8.3434e-02, c: 7.3117e-02, d: 1.0310e-02, s: 5.6738e-01, l1_reg: 6.2127e+02, l2_reg: 9.6918e+01\n",
      "2020/09/08, 20:18:09, Iteration: 800, Train Loss: 6.9941e-02, c: 6.0165e-02, d: 9.7685e-03, s: 5.8719e-01, l1_reg: 6.2190e+02, l2_reg: 9.7080e+01\n",
      "2020/09/08, 20:18:10, Iteration: 900, Train Loss: 1.1648e-01, c: 1.0637e-01, d: 1.0104e-02, s: 5.8001e-01, l1_reg: 6.2119e+02, l2_reg: 9.6844e+01\n",
      "2020/09/08, 20:18:10, Iteration: 1000, Train Loss: 7.7242e-02, c: 6.7403e-02, d: 9.8313e-03, s: 5.8574e-01, l1_reg: 6.2100e+02, l2_reg: 9.6777e+01\n",
      "2020/09/08, 20:18:11, Iteration: 1100, Train Loss: 1.1615e-01, c: 1.0631e-01, d: 9.8263e-03, s: 5.7502e-01, l1_reg: 6.2061e+02, l2_reg: 9.6638e+01\n",
      "2020/09/08, 20:18:12, Iteration: 1200, Train Loss: 6.8190e-02, c: 5.8732e-02, d: 9.4509e-03, s: 5.9022e-01, l1_reg: 6.2076e+02, l2_reg: 9.6668e+01\n",
      "2020/09/08, 20:18:13, Iteration: 1300, Train Loss: 6.6325e-02, c: 5.7125e-02, d: 9.1935e-03, s: 6.0028e-01, l1_reg: 6.2116e+02, l2_reg: 9.6770e+01\n",
      "2020/09/08, 20:18:13, Iteration: 1400, Train Loss: 1.2962e-01, c: 1.1230e-01, d: 1.7316e-02, s: 5.9078e-01, l1_reg: 6.2082e+02, l2_reg: 9.6659e+01\n",
      "2020/09/08, 20:18:14, Iteration: 1500, Train Loss: 8.3816e-02, c: 7.4950e-02, d: 8.8585e-03, s: 5.9673e-01, l1_reg: 6.2050e+02, l2_reg: 9.6548e+01\n",
      "2020/09/08, 20:18:15, Iteration: 1600, Train Loss: 1.3881e-01, c: 1.2213e-01, d: 1.6667e-02, s: 6.0211e-01, l1_reg: 6.2030e+02, l2_reg: 9.6481e+01\n",
      "2020/09/08, 20:18:15, Iteration: 1700, Train Loss: 6.3690e-02, c: 5.4648e-02, d: 9.0353e-03, s: 6.0734e-01, l1_reg: 6.2056e+02, l2_reg: 9.6544e+01\n",
      "2020/09/08, 20:18:16, Iteration: 1800, Train Loss: 1.5655e-01, c: 1.4784e-01, d: 8.7097e-03, s: 6.2281e-01, l1_reg: 6.2097e+02, l2_reg: 9.6660e+01\n",
      "2020/09/08, 20:18:17, Iteration: 1900, Train Loss: 1.9025e-01, c: 1.7155e-01, d: 1.8689e-02, s: 6.0881e-01, l1_reg: 6.2020e+02, l2_reg: 9.6412e+01\n",
      "2020/09/08, 20:18:17, Iteration: 2000, Train Loss: 8.8105e-02, c: 7.9155e-02, d: 8.9426e-03, s: 6.0662e-01, l1_reg: 6.2012e+02, l2_reg: 9.6386e+01\n",
      "2020/09/08, 20:18:18, Iteration: 2100, Train Loss: 5.9943e-02, c: 5.1218e-02, d: 8.7172e-03, s: 6.1918e-01, l1_reg: 6.2046e+02, l2_reg: 9.6481e+01\n",
      "2020/09/08, 20:18:19, Iteration: 2200, Train Loss: 1.7964e-01, c: 1.7023e-01, d: 9.4068e-03, s: 6.2686e-01, l1_reg: 6.2033e+02, l2_reg: 9.6434e+01\n",
      "2020/09/08, 20:18:20, Iteration: 2300, Train Loss: 1.2762e-01, c: 1.1515e-01, d: 1.2457e-02, s: 6.1882e-01, l1_reg: 6.1999e+02, l2_reg: 9.6333e+01\n",
      "2020/09/08, 20:18:20, Iteration: 2400, Train Loss: 1.1475e-01, c: 1.0647e-01, d: 8.2717e-03, s: 6.1990e-01, l1_reg: 6.1971e+02, l2_reg: 9.6251e+01\n",
      "2020/09/08, 20:18:21, Iteration: 2500, Train Loss: 9.9833e-02, c: 9.1127e-02, d: 8.6989e-03, s: 6.0964e-01, l1_reg: 6.1967e+02, l2_reg: 9.6240e+01\n",
      "2020/09/08, 20:18:22, Iteration: 2600, Train Loss: 5.9961e-02, c: 5.1319e-02, d: 8.6353e-03, s: 6.2797e-01, l1_reg: 6.1979e+02, l2_reg: 9.6271e+01\n",
      "2020/09/08, 20:18:22, Iteration: 2700, Train Loss: 9.7066e-02, c: 8.7711e-02, d: 9.3471e-03, s: 6.3935e-01, l1_reg: 6.2017e+02, l2_reg: 9.6381e+01\n",
      "2020/09/08, 20:18:23, Iteration: 2800, Train Loss: 1.2278e-01, c: 1.1379e-01, d: 8.9815e-03, s: 6.3457e-01, l1_reg: 6.2003e+02, l2_reg: 9.6328e+01\n",
      "2020/09/08, 20:18:24, Iteration: 2900, Train Loss: 1.1873e-01, c: 1.1095e-01, d: 7.7712e-03, s: 6.2904e-01, l1_reg: 6.1959e+02, l2_reg: 9.6195e+01\n",
      "2020/09/08, 20:18:24, Iteration: 3000, Train Loss: 8.7629e-02, c: 7.9393e-02, d: 8.2286e-03, s: 6.2540e-01, l1_reg: 6.1960e+02, l2_reg: 9.6195e+01\n",
      "2020/09/08, 20:18:25, Iteration: 3100, Train Loss: 1.5051e-01, c: 1.4071e-01, d: 9.7911e-03, s: 6.4355e-01, l1_reg: 6.1969e+02, l2_reg: 9.6222e+01\n",
      "2020/09/08, 20:18:26, Iteration: 3200, Train Loss: 5.5794e-02, c: 4.7476e-02, d: 8.3110e-03, s: 6.5032e-01, l1_reg: 6.1983e+02, l2_reg: 9.6251e+01\n",
      "2020/09/08, 20:18:27, Iteration: 3300, Train Loss: 1.5637e-01, c: 1.4541e-01, d: 1.0950e-02, s: 6.5304e-01, l1_reg: 6.2009e+02, l2_reg: 9.6320e+01\n",
      "2020/09/08, 20:18:27, Iteration: 3400, Train Loss: 1.0958e-01, c: 1.0169e-01, d: 7.8810e-03, s: 6.4737e-01, l1_reg: 6.1976e+02, l2_reg: 9.6217e+01\n",
      "2020/09/08, 20:18:28, Iteration: 3500, Train Loss: 8.9211e-02, c: 8.0613e-02, d: 8.5911e-03, s: 6.5624e-01, l1_reg: 6.1964e+02, l2_reg: 9.6171e+01\n",
      "2020/09/08, 20:18:29, Iteration: 3600, Train Loss: 1.2608e-01, c: 1.1805e-01, d: 8.0215e-03, s: 6.5883e-01, l1_reg: 6.1984e+02, l2_reg: 9.6221e+01\n",
      "2020/09/08, 20:18:29, Iteration: 3700, Train Loss: 1.6133e-01, c: 1.4825e-01, d: 1.3074e-02, s: 6.4787e-01, l1_reg: 6.1956e+02, l2_reg: 9.6136e+01\n",
      "2020/09/08, 20:18:30, Iteration: 3800, Train Loss: 5.4222e-02, c: 4.6347e-02, d: 7.8680e-03, s: 6.6525e-01, l1_reg: 6.1972e+02, l2_reg: 9.6183e+01\n",
      "2020/09/08, 20:18:31, Iteration: 3900, Train Loss: 2.2344e-01, c: 2.1109e-01, d: 1.2344e-02, s: 6.5648e-01, l1_reg: 6.1963e+02, l2_reg: 9.6145e+01\n",
      "2020/09/08, 20:18:31, Iteration: 4000, Train Loss: 1.9421e-01, c: 1.8510e-01, d: 9.1047e-03, s: 6.7453e-01, l1_reg: 6.1979e+02, l2_reg: 9.6199e+01\n",
      "2020/09/08, 20:18:32, Iteration: 4100, Train Loss: 1.6198e-01, c: 1.5070e-01, d: 1.1273e-02, s: 6.7639e-01, l1_reg: 6.1964e+02, l2_reg: 9.6145e+01\n",
      "2020/09/08, 20:18:33, Iteration: 4200, Train Loss: 1.1923e-01, c: 1.1051e-01, d: 8.7094e-03, s: 6.7625e-01, l1_reg: 6.1931e+02, l2_reg: 9.6053e+01\n",
      "2020/09/08, 20:18:33, Iteration: 4300, Train Loss: 5.2891e-02, c: 4.5106e-02, d: 7.7778e-03, s: 6.7911e-01, l1_reg: 6.1938e+02, l2_reg: 9.6068e+01\n",
      "2020/09/08, 20:18:34, Iteration: 4400, Train Loss: 5.4186e-02, c: 4.5830e-02, d: 8.3494e-03, s: 6.8110e-01, l1_reg: 6.1959e+02, l2_reg: 9.6121e+01\n",
      "2020/09/08, 20:18:35, Iteration: 4500, Train Loss: 1.1963e-01, c: 1.1138e-01, d: 8.2362e-03, s: 6.7971e-01, l1_reg: 6.1950e+02, l2_reg: 9.6092e+01\n",
      "2020/09/08, 20:18:36, Iteration: 4600, Train Loss: 6.2547e-02, c: 5.4668e-02, d: 7.8712e-03, s: 6.9259e-01, l1_reg: 6.1960e+02, l2_reg: 9.6119e+01\n",
      "2020/09/08, 20:18:36, Iteration: 4700, Train Loss: 1.0284e-01, c: 9.5398e-02, d: 7.4367e-03, s: 6.9379e-01, l1_reg: 6.1956e+02, l2_reg: 9.6105e+01\n",
      "2020/09/08, 20:18:37, Iteration: 4800, Train Loss: 7.8740e-02, c: 6.9778e-02, d: 8.9550e-03, s: 6.9891e-01, l1_reg: 6.1958e+02, l2_reg: 9.6116e+01\n",
      "2020/09/08, 20:18:38, Iteration: 4900, Train Loss: 1.9349e-01, c: 1.8451e-01, d: 8.9764e-03, s: 7.0017e-01, l1_reg: 6.1928e+02, l2_reg: 9.6025e+01\n",
      "2020/09/08, 20:18:38, Iteration: 5000, Train Loss: 8.4436e-02, c: 7.6716e-02, d: 7.7126e-03, s: 7.1020e-01, l1_reg: 6.1940e+02, l2_reg: 9.6063e+01\n",
      "2020/09/08, 20:18:39, Iteration: 5100, Train Loss: 6.0967e-02, c: 5.3241e-02, d: 7.7183e-03, s: 7.0756e-01, l1_reg: 6.1944e+02, l2_reg: 9.6072e+01\n",
      "2020/09/08, 20:18:40, Iteration: 5200, Train Loss: 7.9958e-02, c: 7.1885e-02, d: 8.0663e-03, s: 7.0833e-01, l1_reg: 6.1943e+02, l2_reg: 9.6066e+01\n",
      "2020/09/08, 20:18:40, Iteration: 5300, Train Loss: 2.0240e-01, c: 1.9337e-01, d: 9.0203e-03, s: 7.2758e-01, l1_reg: 6.1958e+02, l2_reg: 9.6125e+01\n",
      "2020/09/08, 20:18:41, Iteration: 5400, Train Loss: 5.3424e-02, c: 4.6389e-02, d: 7.0284e-03, s: 7.1345e-01, l1_reg: 6.1929e+02, l2_reg: 9.6027e+01\n",
      "2020/09/08, 20:18:42, Iteration: 5500, Train Loss: 1.3389e-01, c: 1.2655e-01, d: 7.3339e-03, s: 7.3587e-01, l1_reg: 6.1966e+02, l2_reg: 9.6134e+01\n",
      "2020/09/08, 20:18:42, Iteration: 5600, Train Loss: 1.6809e-01, c: 1.5652e-01, d: 1.1563e-02, s: 7.2646e-01, l1_reg: 6.1925e+02, l2_reg: 9.6012e+01\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020/09/08, 20:18:43, Iteration: 5700, Train Loss: 4.7722e-02, c: 4.0486e-02, d: 7.2281e-03, s: 7.3720e-01, l1_reg: 6.1939e+02, l2_reg: 9.6047e+01\n",
      "2020/09/08, 20:18:44, Iteration: 5800, Train Loss: 1.8265e-01, c: 1.7399e-01, d: 8.6617e-03, s: 7.4051e-01, l1_reg: 6.1948e+02, l2_reg: 9.6077e+01\n",
      "2020/09/08, 20:18:44, Iteration: 5900, Train Loss: 5.4490e-02, c: 4.6318e-02, d: 8.1644e-03, s: 7.3233e-01, l1_reg: 6.1931e+02, l2_reg: 9.6021e+01\n",
      "2020/09/08, 20:18:45, Iteration: 6000, Train Loss: 7.7146e-02, c: 6.7854e-02, d: 9.2841e-03, s: 7.4667e-01, l1_reg: 6.1941e+02, l2_reg: 9.6055e+01\n",
      "2020/09/08, 20:18:46, Iteration: 6100, Train Loss: 1.5771e-01, c: 1.4275e-01, d: 1.4945e-02, s: 7.2951e-01, l1_reg: 6.1908e+02, l2_reg: 9.5959e+01\n",
      "2020/09/08, 20:18:46, Iteration: 6200, Train Loss: 9.1739e-02, c: 8.4222e-02, d: 7.5096e-03, s: 7.4674e-01, l1_reg: 6.1908e+02, l2_reg: 9.5972e+01\n",
      "2020/09/08, 20:18:47, Iteration: 6300, Train Loss: 1.3572e-01, c: 1.2853e-01, d: 7.1841e-03, s: 7.6459e-01, l1_reg: 6.1912e+02, l2_reg: 9.5980e+01\n",
      "2020/09/08, 20:18:48, Iteration: 6400, Train Loss: 6.6093e-02, c: 5.9615e-02, d: 6.4703e-03, s: 7.5652e-01, l1_reg: 6.1918e+02, l2_reg: 9.5998e+01\n",
      "2020/09/08, 20:18:48, Iteration: 6500, Train Loss: 1.3756e-01, c: 1.2956e-01, d: 7.9884e-03, s: 7.7207e-01, l1_reg: 6.1933e+02, l2_reg: 9.6051e+01\n",
      "2020/09/08, 20:18:49, Iteration: 6600, Train Loss: 1.4435e-01, c: 1.3736e-01, d: 6.9750e-03, s: 7.7734e-01, l1_reg: 6.1935e+02, l2_reg: 9.6054e+01\n",
      "2020/09/08, 20:18:50, Iteration: 6700, Train Loss: 1.2482e-01, c: 1.1660e-01, d: 8.2181e-03, s: 7.6774e-01, l1_reg: 6.1922e+02, l2_reg: 9.6023e+01\n",
      "2020/09/08, 20:18:51, Iteration: 6800, Train Loss: 1.2018e-01, c: 1.0809e-01, d: 1.2080e-02, s: 7.7394e-01, l1_reg: 6.1904e+02, l2_reg: 9.5975e+01\n",
      "2020/09/08, 20:18:51, Iteration: 6900, Train Loss: 5.4148e-02, c: 4.7719e-02, d: 6.4217e-03, s: 7.8087e-01, l1_reg: 6.1913e+02, l2_reg: 9.5997e+01\n",
      "2020/09/08, 20:18:52, Iteration: 7000, Train Loss: 1.7964e-01, c: 1.6895e-01, d: 1.0684e-02, s: 7.8175e-01, l1_reg: 6.1900e+02, l2_reg: 9.5967e+01\n",
      "2020/09/08, 20:18:53, Iteration: 7100, Train Loss: 1.2464e-01, c: 1.1832e-01, d: 6.3157e-03, s: 7.7908e-01, l1_reg: 6.1895e+02, l2_reg: 9.5961e+01\n",
      "2020/09/08, 20:18:53, Iteration: 7200, Train Loss: 5.9733e-02, c: 5.1848e-02, d: 7.8780e-03, s: 7.9444e-01, l1_reg: 6.1916e+02, l2_reg: 9.6030e+01\n",
      "2020/09/08, 20:18:54, Iteration: 7300, Train Loss: 6.4788e-02, c: 5.6217e-02, d: 8.5644e-03, s: 7.9898e-01, l1_reg: 6.1904e+02, l2_reg: 9.5996e+01\n",
      "2020/09/08, 20:18:55, Iteration: 7400, Train Loss: 9.1562e-02, c: 8.4249e-02, d: 7.3054e-03, s: 7.9425e-01, l1_reg: 6.1907e+02, l2_reg: 9.6005e+01\n",
      "2020/09/08, 20:18:55, Iteration: 7500, Train Loss: 8.8304e-02, c: 8.1819e-02, d: 6.4781e-03, s: 7.9255e-01, l1_reg: 6.1918e+02, l2_reg: 9.6044e+01\n",
      "2020/09/08, 20:18:56, Iteration: 7600, Train Loss: 1.8196e-01, c: 1.7521e-01, d: 6.7457e-03, s: 8.0827e-01, l1_reg: 6.1900e+02, l2_reg: 9.5991e+01\n",
      "2020/09/08, 20:18:57, Iteration: 7700, Train Loss: 6.7791e-02, c: 6.1204e-02, d: 6.5802e-03, s: 8.2220e-01, l1_reg: 6.1918e+02, l2_reg: 9.6059e+01\n",
      "2020/09/08, 20:18:57, Iteration: 7800, Train Loss: 7.8594e-02, c: 7.3315e-02, d: 5.2713e-03, s: 8.2901e-01, l1_reg: 6.1918e+02, l2_reg: 9.6063e+01\n",
      "2020/09/08, 20:18:58, Iteration: 7900, Train Loss: 8.3059e-02, c: 7.7126e-02, d: 5.9260e-03, s: 8.3261e-01, l1_reg: 6.1920e+02, l2_reg: 9.6078e+01\n",
      "2020/09/08, 20:18:59, Iteration: 8000, Train Loss: 1.7651e-01, c: 1.6778e-01, d: 8.7161e-03, s: 8.3995e-01, l1_reg: 6.1937e+02, l2_reg: 9.6134e+01\n",
      "2020/09/08, 20:19:00, Iteration: 8100, Train Loss: 1.3070e-01, c: 1.2486e-01, d: 5.8290e-03, s: 8.3470e-01, l1_reg: 6.1915e+02, l2_reg: 9.6079e+01\n",
      "2020/09/08, 20:19:00, Iteration: 8200, Train Loss: 1.0748e-01, c: 1.0177e-01, d: 5.7049e-03, s: 8.4573e-01, l1_reg: 6.1943e+02, l2_reg: 9.6173e+01\n",
      "2020/09/08, 20:19:01, Iteration: 8300, Train Loss: 8.6779e-02, c: 8.0270e-02, d: 6.5021e-03, s: 8.5564e-01, l1_reg: 6.1925e+02, l2_reg: 9.6130e+01\n",
      "2020/09/08, 20:19:02, Iteration: 8400, Train Loss: 1.6958e-01, c: 1.6289e-01, d: 6.6809e-03, s: 8.5633e-01, l1_reg: 6.1944e+02, l2_reg: 9.6195e+01\n",
      "2020/09/08, 20:19:02, Iteration: 8500, Train Loss: 9.9165e-02, c: 8.7428e-02, d: 1.1731e-02, s: 8.3691e-01, l1_reg: 6.1916e+02, l2_reg: 9.6115e+01\n",
      "2020/09/08, 20:19:03, Iteration: 8600, Train Loss: 5.5215e-02, c: 4.7351e-02, d: 7.8563e-03, s: 8.5659e-01, l1_reg: 6.1929e+02, l2_reg: 9.6171e+01\n",
      "2020/09/08, 20:19:04, Iteration: 8700, Train Loss: 9.2162e-02, c: 8.3404e-02, d: 8.7510e-03, s: 8.7057e-01, l1_reg: 6.1919e+02, l2_reg: 9.6147e+01\n",
      "2020/09/08, 20:19:04, Iteration: 8800, Train Loss: 5.2247e-02, c: 4.6231e-02, d: 6.0092e-03, s: 8.6940e-01, l1_reg: 6.1929e+02, l2_reg: 9.6190e+01\n",
      "2020/09/08, 20:19:05, Iteration: 8900, Train Loss: 1.1639e-01, c: 1.1093e-01, d: 5.4572e-03, s: 8.7637e-01, l1_reg: 6.1917e+02, l2_reg: 9.6168e+01\n",
      "2020/09/08, 20:19:06, Iteration: 9000, Train Loss: 6.9589e-02, c: 6.2592e-02, d: 6.9891e-03, s: 8.6982e-01, l1_reg: 6.1933e+02, l2_reg: 9.6226e+01\n",
      "2020/09/08, 20:19:07, Iteration: 9100, Train Loss: 4.1084e-02, c: 3.3307e-02, d: 7.7692e-03, s: 8.8094e-01, l1_reg: 6.1937e+02, l2_reg: 9.6244e+01\n",
      "2020/09/08, 20:19:07, Iteration: 9200, Train Loss: 9.5144e-02, c: 8.8492e-02, d: 6.6452e-03, s: 8.7692e-01, l1_reg: 6.1950e+02, l2_reg: 9.6295e+01\n",
      "2020/09/08, 20:19:08, Iteration: 9300, Train Loss: 5.8584e-02, c: 5.3209e-02, d: 5.3677e-03, s: 8.9735e-01, l1_reg: 6.1951e+02, l2_reg: 9.6311e+01\n",
      "2020/09/08, 20:19:09, Iteration: 9400, Train Loss: 8.1448e-02, c: 7.6373e-02, d: 5.0681e-03, s: 9.1053e-01, l1_reg: 6.1957e+02, l2_reg: 9.6344e+01\n",
      "2020/09/08, 20:19:09, Iteration: 9500, Train Loss: 7.8504e-02, c: 7.3555e-02, d: 4.9419e-03, s: 9.0868e-01, l1_reg: 6.1936e+02, l2_reg: 9.6296e+01\n",
      "2020/09/08, 20:19:10, Iteration: 9600, Train Loss: 1.1469e-01, c: 1.0568e-01, d: 8.9985e-03, s: 9.1024e-01, l1_reg: 6.1935e+02, l2_reg: 9.6302e+01\n",
      "2020/09/08, 20:19:11, Iteration: 9700, Train Loss: 4.8176e-02, c: 4.0923e-02, d: 7.2458e-03, s: 9.1220e-01, l1_reg: 6.1938e+02, l2_reg: 9.6321e+01\n",
      "2020/09/08, 20:19:12, Iteration: 9800, Train Loss: 3.0852e-02, c: 2.5579e-02, d: 5.2668e-03, s: 9.2103e-01, l1_reg: 6.1944e+02, l2_reg: 9.6352e+01\n",
      "2020/09/08, 20:19:12, Iteration: 9900, Train Loss: 2.6879e-02, c: 2.1839e-02, d: 5.0322e-03, s: 9.1122e-01, l1_reg: 6.1938e+02, l2_reg: 9.6340e+01\n",
      "2020/09/08, 20:19:13, Iteration: 10000, Train Loss: 7.0526e-02, c: 6.5879e-02, d: 4.6400e-03, s: 9.1558e-01, l1_reg: 6.1929e+02, l2_reg: 9.6328e+01\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/lib/python3.8/site-packages/numpy/core/_asarray.py:83: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n",
      "  return array(a, dtype, copy=False, order=order)\n"
     ]
    }
   ],
   "source": [
    "import jax\n",
    "import jax.numpy as jnp\n",
    "\n",
    "import os, sys\n",
    "sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(\"./\")))))\n",
    "\n",
    "from training import Agent\n",
    "from loss import params, loss_fn, evaluate_fn\n",
    "from data import generate_dataset, generate_batch_fn\n",
    "\n",
    "import config\n",
    "config.n_data = {\n",
    "\t\"b\": 2,\n",
    "    \"c\": 1000,\n",
    "    \"d\": 100,\n",
    "}\n",
    "config.batch_size = {\n",
    "    \"dirichlet\": 102,\n",
    "    \"collocation\": 1100,\n",
    "}\n",
    "config.iterations = 10000\n",
    "config.print_every = 100\n",
    "\n",
    "datasets = generate_dataset(config.n_data[\"b\"], config.n_data[\"c\"], config.n_data[\"d\"])\n",
    "batch_fn, evaluate_batch_fn = generate_batch_fn(config.key, config.batch_size, *datasets, config.weights)\n",
    "\n",
    "agent = Agent(params, loss_fn, evaluate_fn, \"models/{}\".format(config.NAME))\n",
    "agent.compile(config.optimizer, config.lr)\n",
    "agent.train(config.iterations, batch_fn, evaluate_batch_fn, config.print_every, config.save_every, config.loss_names, config.log_file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2020/09/08, 20:19:28, Iteration: 10200, Train Loss: 9.7649e-02, c: 8.9103e-02, d: 8.5384e-03, s: 9.1896e-01, l1_reg: 6.1924e+02, l2_reg: 9.6334e+01\n",
      "2020/09/08, 20:19:30, Iteration: 10400, Train Loss: 1.2382e-01, c: 1.1859e-01, d: 5.2263e-03, s: 9.4200e-01, l1_reg: 6.1936e+02, l2_reg: 9.6387e+01\n",
      "2020/09/08, 20:19:31, Iteration: 10600, Train Loss: 6.4363e-02, c: 5.9781e-02, d: 4.5757e-03, s: 9.5211e-01, l1_reg: 6.1925e+02, l2_reg: 9.6386e+01\n",
      "2020/09/08, 20:19:32, Iteration: 10800, Train Loss: 3.5772e-02, c: 3.0122e-02, d: 5.6431e-03, s: 9.5484e-01, l1_reg: 6.1918e+02, l2_reg: 9.6380e+01\n",
      "2020/09/08, 20:19:34, Iteration: 11000, Train Loss: 1.0490e-01, c: 9.7956e-02, d: 6.9396e-03, s: 9.8201e-01, l1_reg: 6.1923e+02, l2_reg: 9.6419e+01\n",
      "2020/09/08, 20:19:35, Iteration: 11200, Train Loss: 5.8186e-02, c: 5.2567e-02, d: 5.6122e-03, s: 9.7551e-01, l1_reg: 6.1903e+02, l2_reg: 9.6378e+01\n",
      "2020/09/08, 20:19:37, Iteration: 11400, Train Loss: 5.2464e-02, c: 4.9483e-02, d: 2.9735e-03, s: 9.8765e-01, l1_reg: 6.1881e+02, l2_reg: 9.6329e+01\n",
      "2020/09/08, 20:19:38, Iteration: 11600, Train Loss: 5.6907e-02, c: 5.3969e-02, d: 2.9306e-03, s: 9.8888e-01, l1_reg: 6.1880e+02, l2_reg: 9.6346e+01\n",
      "2020/09/08, 20:19:40, Iteration: 11800, Train Loss: 5.8253e-02, c: 5.4849e-02, d: 3.3966e-03, s: 1.0207e+00, l1_reg: 6.1887e+02, l2_reg: 9.6398e+01\n",
      "2020/09/08, 20:19:41, Iteration: 12000, Train Loss: 8.2448e-02, c: 7.9206e-02, d: 3.2345e-03, s: 1.0207e+00, l1_reg: 6.1861e+02, l2_reg: 9.6331e+01\n",
      "2020/09/08, 20:19:42, Iteration: 12200, Train Loss: 7.9364e-02, c: 7.4999e-02, d: 4.3576e-03, s: 1.0304e+00, l1_reg: 6.1866e+02, l2_reg: 9.6365e+01\n",
      "2020/09/08, 20:19:44, Iteration: 12400, Train Loss: 5.0132e-02, c: 4.7427e-02, d: 2.6981e-03, s: 1.0233e+00, l1_reg: 6.1836e+02, l2_reg: 9.6280e+01\n",
      "2020/09/08, 20:19:45, Iteration: 12600, Train Loss: 5.2301e-02, c: 4.9903e-02, d: 2.3901e-03, s: 1.0318e+00, l1_reg: 6.1823e+02, l2_reg: 9.6257e+01\n",
      "2020/09/08, 20:19:47, Iteration: 12800, Train Loss: 3.5455e-02, c: 3.1907e-02, d: 3.5414e-03, s: 1.0407e+00, l1_reg: 6.1828e+02, l2_reg: 9.6287e+01\n",
      "2020/09/08, 20:19:48, Iteration: 13000, Train Loss: 9.4408e-02, c: 9.0814e-02, d: 3.5862e-03, s: 1.0411e+00, l1_reg: 6.1802e+02, l2_reg: 9.6227e+01\n",
      "2020/09/08, 20:19:49, Iteration: 13200, Train Loss: 7.6925e-02, c: 6.8874e-02, d: 8.0445e-03, s: 1.0653e+00, l1_reg: 6.1798e+02, l2_reg: 9.6230e+01\n",
      "2020/09/08, 20:19:51, Iteration: 13400, Train Loss: 6.7485e-02, c: 6.3461e-02, d: 4.0167e-03, s: 1.0493e+00, l1_reg: 6.1780e+02, l2_reg: 9.6184e+01\n",
      "2020/09/08, 20:19:52, Iteration: 13600, Train Loss: 6.2889e-02, c: 5.7942e-02, d: 4.9399e-03, s: 1.0567e+00, l1_reg: 6.1781e+02, l2_reg: 9.6208e+01\n",
      "2020/09/08, 20:19:53, Iteration: 13800, Train Loss: 5.9401e-02, c: 5.3947e-02, d: 5.4471e-03, s: 1.0679e+00, l1_reg: 6.1769e+02, l2_reg: 9.6188e+01\n",
      "2020/09/08, 20:19:55, Iteration: 14000, Train Loss: 6.0911e-02, c: 5.8515e-02, d: 2.3883e-03, s: 1.0713e+00, l1_reg: 6.1734e+02, l2_reg: 9.6110e+01\n",
      "2020/09/08, 20:19:56, Iteration: 14200, Train Loss: 6.5984e-02, c: 6.3669e-02, d: 2.3076e-03, s: 1.0728e+00, l1_reg: 6.1717e+02, l2_reg: 9.6076e+01\n",
      "2020/09/08, 20:19:58, Iteration: 14400, Train Loss: 9.0558e-02, c: 8.5977e-02, d: 4.5742e-03, s: 1.0756e+00, l1_reg: 6.1697e+02, l2_reg: 9.6022e+01\n",
      "2020/09/08, 20:19:59, Iteration: 14600, Train Loss: 1.3230e-01, c: 1.2907e-01, d: 3.2132e-03, s: 1.0759e+00, l1_reg: 6.1675e+02, l2_reg: 9.5979e+01\n",
      "2020/09/08, 20:20:00, Iteration: 14800, Train Loss: 3.2560e-02, c: 2.9647e-02, d: 2.9059e-03, s: 1.0702e+00, l1_reg: 6.1672e+02, l2_reg: 9.5985e+01\n",
      "2020/09/08, 20:20:02, Iteration: 15000, Train Loss: 6.2300e-02, c: 5.9285e-02, d: 3.0081e-03, s: 1.0670e+00, l1_reg: 6.1637e+02, l2_reg: 9.5887e+01\n",
      "2020/09/08, 20:20:03, Iteration: 15200, Train Loss: 3.9798e-02, c: 3.8048e-02, d: 1.7430e-03, s: 1.0792e+00, l1_reg: 6.1631e+02, l2_reg: 9.5893e+01\n",
      "2020/09/08, 20:20:05, Iteration: 15400, Train Loss: 5.6020e-02, c: 4.9020e-02, d: 6.9935e-03, s: 1.0844e+00, l1_reg: 6.1629e+02, l2_reg: 9.5903e+01\n",
      "2020/09/08, 20:20:06, Iteration: 15600, Train Loss: 8.6227e-02, c: 8.2680e-02, d: 3.5401e-03, s: 1.0799e+00, l1_reg: 6.1610e+02, l2_reg: 9.5846e+01\n",
      "2020/09/08, 20:20:07, Iteration: 15800, Train Loss: 3.2404e-02, c: 3.0535e-02, d: 1.8622e-03, s: 1.0746e+00, l1_reg: 6.1574e+02, l2_reg: 9.5758e+01\n",
      "2020/09/08, 20:20:09, Iteration: 16000, Train Loss: 4.3436e-02, c: 4.0948e-02, d: 2.4805e-03, s: 1.0704e+00, l1_reg: 6.1542e+02, l2_reg: 9.5674e+01\n",
      "2020/09/08, 20:20:10, Iteration: 16200, Train Loss: 4.6555e-02, c: 4.4645e-02, d: 1.9033e-03, s: 1.0751e+00, l1_reg: 6.1512e+02, l2_reg: 9.5597e+01\n",
      "2020/09/08, 20:20:11, Iteration: 16400, Train Loss: 6.5326e-02, c: 6.2347e-02, d: 2.9715e-03, s: 1.0821e+00, l1_reg: 6.1497e+02, l2_reg: 9.5573e+01\n",
      "2020/09/08, 20:20:13, Iteration: 16600, Train Loss: 6.8876e-02, c: 6.5530e-02, d: 3.3394e-03, s: 1.0801e+00, l1_reg: 6.1492e+02, l2_reg: 9.5572e+01\n",
      "2020/09/08, 20:20:14, Iteration: 16800, Train Loss: 3.4714e-02, c: 3.2259e-02, d: 2.4475e-03, s: 1.0864e+00, l1_reg: 6.1474e+02, l2_reg: 9.5529e+01\n",
      "2020/09/08, 20:20:15, Iteration: 17000, Train Loss: 3.4241e-02, c: 2.7442e-02, d: 6.7922e-03, s: 1.0798e+00, l1_reg: 6.1453e+02, l2_reg: 9.5472e+01\n",
      "2020/09/08, 20:20:17, Iteration: 17200, Train Loss: 2.7414e-02, c: 2.3560e-02, d: 3.8467e-03, s: 1.0939e+00, l1_reg: 6.1430e+02, l2_reg: 9.5425e+01\n",
      "2020/09/08, 20:20:18, Iteration: 17400, Train Loss: 1.2976e-01, c: 1.2571e-01, d: 4.0428e-03, s: 1.0948e+00, l1_reg: 6.1409e+02, l2_reg: 9.5379e+01\n",
      "2020/09/08, 20:20:19, Iteration: 17600, Train Loss: 4.6964e-02, c: 4.1864e-02, d: 5.0937e-03, s: 1.0869e+00, l1_reg: 6.1377e+02, l2_reg: 9.5306e+01\n",
      "2020/09/08, 20:20:21, Iteration: 17800, Train Loss: 5.6661e-02, c: 5.1009e-02, d: 5.6446e-03, s: 1.0748e+00, l1_reg: 6.1353e+02, l2_reg: 9.5256e+01\n",
      "2020/09/08, 20:20:22, Iteration: 18000, Train Loss: 5.9569e-02, c: 5.6785e-02, d: 2.7773e-03, s: 1.0903e+00, l1_reg: 6.1358e+02, l2_reg: 9.5286e+01\n",
      "2020/09/08, 20:20:24, Iteration: 18200, Train Loss: 8.3161e-02, c: 7.8311e-02, d: 4.8428e-03, s: 1.0910e+00, l1_reg: 6.1322e+02, l2_reg: 9.5190e+01\n",
      "2020/09/08, 20:20:25, Iteration: 18400, Train Loss: 8.9493e-02, c: 8.6281e-02, d: 3.2042e-03, s: 1.0842e+00, l1_reg: 6.1299e+02, l2_reg: 9.5154e+01\n",
      "2020/09/08, 20:20:26, Iteration: 18600, Train Loss: 1.1398e-01, c: 1.0980e-01, d: 4.1736e-03, s: 1.0950e+00, l1_reg: 6.1276e+02, l2_reg: 9.5105e+01\n",
      "2020/09/08, 20:20:28, Iteration: 18800, Train Loss: 6.5394e-02, c: 6.3436e-02, d: 1.9505e-03, s: 1.0915e+00, l1_reg: 6.1277e+02, l2_reg: 9.5118e+01\n",
      "2020/09/08, 20:20:29, Iteration: 19000, Train Loss: 8.7902e-02, c: 8.1320e-02, d: 6.5747e-03, s: 1.0833e+00, l1_reg: 6.1235e+02, l2_reg: 9.5011e+01\n",
      "2020/09/08, 20:20:30, Iteration: 19200, Train Loss: 2.8194e-02, c: 2.6259e-02, d: 1.9280e-03, s: 1.0935e+00, l1_reg: 6.1222e+02, l2_reg: 9.5005e+01\n",
      "2020/09/08, 20:20:32, Iteration: 19400, Train Loss: 5.9579e-02, c: 5.6787e-02, d: 2.7849e-03, s: 1.0923e+00, l1_reg: 6.1197e+02, l2_reg: 9.4959e+01\n",
      "2020/09/08, 20:20:33, Iteration: 19600, Train Loss: 9.5672e-02, c: 9.1017e-02, d: 4.6480e-03, s: 1.0943e+00, l1_reg: 6.1191e+02, l2_reg: 9.4968e+01\n",
      "2020/09/08, 20:20:35, Iteration: 19800, Train Loss: 6.2007e-02, c: 5.7759e-02, d: 4.2405e-03, s: 1.0970e+00, l1_reg: 6.1163e+02, l2_reg: 9.4906e+01\n",
      "2020/09/08, 20:20:36, Iteration: 20000, Train Loss: 5.9966e-02, c: 5.6034e-02, d: 3.9253e-03, s: 1.0922e+00, l1_reg: 6.1151e+02, l2_reg: 9.4896e+01\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/lib/python3.8/site-packages/numpy/core/_asarray.py:83: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray\n",
      "  return array(a, dtype, copy=False, order=order)\n"
     ]
    }
   ],
   "source": [
    "config.iterations = 10000\n",
    "config.print_every = 200\n",
    "agent.train(config.iterations, batch_fn, evaluate_batch_fn, config.print_every, config.save_every, config.loss_names, config.log_file)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "/* Put everything inside the global mpl namespace */\n",
       "/* global mpl */\n",
       "window.mpl = {};\n",
       "\n",
       "mpl.get_websocket_type = function () {\n",
       "    if (typeof WebSocket !== 'undefined') {\n",
       "        return WebSocket;\n",
       "    } else if (typeof MozWebSocket !== 'undefined') {\n",
       "        return MozWebSocket;\n",
       "    } else {\n",
       "        alert(\n",
       "            'Your browser does not have WebSocket support. ' +\n",
       "                'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
       "                'Firefox 4 and 5 are also supported but you ' +\n",
       "                'have to enable WebSockets in about:config.'\n",
       "        );\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure = function (figure_id, websocket, ondownload, parent_element) {\n",
       "    this.id = figure_id;\n",
       "\n",
       "    this.ws = websocket;\n",
       "\n",
       "    this.supports_binary = this.ws.binaryType !== undefined;\n",
       "\n",
       "    if (!this.supports_binary) {\n",
       "        var warnings = document.getElementById('mpl-warnings');\n",
       "        if (warnings) {\n",
       "            warnings.style.display = 'block';\n",
       "            warnings.textContent =\n",
       "                'This browser does not support binary websocket messages. ' +\n",
       "                'Performance may be slow.';\n",
       "        }\n",
       "    }\n",
       "\n",
       "    this.imageObj = new Image();\n",
       "\n",
       "    this.context = undefined;\n",
       "    this.message = undefined;\n",
       "    this.canvas = undefined;\n",
       "    this.rubberband_canvas = undefined;\n",
       "    this.rubberband_context = undefined;\n",
       "    this.format_dropdown = undefined;\n",
       "\n",
       "    this.image_mode = 'full';\n",
       "\n",
       "    this.root = document.createElement('div');\n",
       "    this.root.setAttribute('style', 'display: inline-block');\n",
       "    this._root_extra_style(this.root);\n",
       "\n",
       "    parent_element.appendChild(this.root);\n",
       "\n",
       "    this._init_header(this);\n",
       "    this._init_canvas(this);\n",
       "    this._init_toolbar(this);\n",
       "\n",
       "    var fig = this;\n",
       "\n",
       "    this.waiting = false;\n",
       "\n",
       "    this.ws.onopen = function () {\n",
       "        fig.send_message('supports_binary', { value: fig.supports_binary });\n",
       "        fig.send_message('send_image_mode', {});\n",
       "        if (mpl.ratio !== 1) {\n",
       "            fig.send_message('set_dpi_ratio', { dpi_ratio: mpl.ratio });\n",
       "        }\n",
       "        fig.send_message('refresh', {});\n",
       "    };\n",
       "\n",
       "    this.imageObj.onload = function () {\n",
       "        if (fig.image_mode === 'full') {\n",
       "            // Full images could contain transparency (where diff images\n",
       "            // almost always do), so we need to clear the canvas so that\n",
       "            // there is no ghosting.\n",
       "            fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
       "        }\n",
       "        fig.context.drawImage(fig.imageObj, 0, 0);\n",
       "    };\n",
       "\n",
       "    this.imageObj.onunload = function () {\n",
       "        fig.ws.close();\n",
       "    };\n",
       "\n",
       "    this.ws.onmessage = this._make_on_message_function(this);\n",
       "\n",
       "    this.ondownload = ondownload;\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._init_header = function () {\n",
       "    var titlebar = document.createElement('div');\n",
       "    titlebar.classList =\n",
       "        'ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix';\n",
       "    var titletext = document.createElement('div');\n",
       "    titletext.classList = 'ui-dialog-title';\n",
       "    titletext.setAttribute(\n",
       "        'style',\n",
       "        'width: 100%; text-align: center; padding: 3px;'\n",
       "    );\n",
       "    titlebar.appendChild(titletext);\n",
       "    this.root.appendChild(titlebar);\n",
       "    this.header = titletext;\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._canvas_extra_style = function (_canvas_div) {};\n",
       "\n",
       "mpl.figure.prototype._root_extra_style = function (_canvas_div) {};\n",
       "\n",
       "mpl.figure.prototype._init_canvas = function () {\n",
       "    var fig = this;\n",
       "\n",
       "    var canvas_div = (this.canvas_div = document.createElement('div'));\n",
       "    canvas_div.setAttribute(\n",
       "        'style',\n",
       "        'border: 1px solid #ddd;' +\n",
       "            'box-sizing: content-box;' +\n",
       "            'clear: both;' +\n",
       "            'min-height: 1px;' +\n",
       "            'min-width: 1px;' +\n",
       "            'outline: 0;' +\n",
       "            'overflow: hidden;' +\n",
       "            'position: relative;' +\n",
       "            'resize: both;'\n",
       "    );\n",
       "\n",
       "    function on_keyboard_event_closure(name) {\n",
       "        return function (event) {\n",
       "            return fig.key_event(event, name);\n",
       "        };\n",
       "    }\n",
       "\n",
       "    canvas_div.addEventListener(\n",
       "        'keydown',\n",
       "        on_keyboard_event_closure('key_press')\n",
       "    );\n",
       "    canvas_div.addEventListener(\n",
       "        'keyup',\n",
       "        on_keyboard_event_closure('key_release')\n",
       "    );\n",
       "\n",
       "    this._canvas_extra_style(canvas_div);\n",
       "    this.root.appendChild(canvas_div);\n",
       "\n",
       "    var canvas = (this.canvas = document.createElement('canvas'));\n",
       "    canvas.classList.add('mpl-canvas');\n",
       "    canvas.setAttribute('style', 'box-sizing: content-box;');\n",
       "\n",
       "    this.context = canvas.getContext('2d');\n",
       "\n",
       "    var backingStore =\n",
       "        this.context.backingStorePixelRatio ||\n",
       "        this.context.webkitBackingStorePixelRatio ||\n",
       "        this.context.mozBackingStorePixelRatio ||\n",
       "        this.context.msBackingStorePixelRatio ||\n",
       "        this.context.oBackingStorePixelRatio ||\n",
       "        this.context.backingStorePixelRatio ||\n",
       "        1;\n",
       "\n",
       "    mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
       "\n",
       "    var rubberband_canvas = (this.rubberband_canvas = document.createElement(\n",
       "        'canvas'\n",
       "    ));\n",
       "    rubberband_canvas.setAttribute(\n",
       "        'style',\n",
       "        'box-sizing: content-box; position: absolute; left: 0; top: 0; z-index: 1;'\n",
       "    );\n",
       "\n",
       "    var resizeObserver = new ResizeObserver(function (entries) {\n",
       "        var nentries = entries.length;\n",
       "        for (var i = 0; i < nentries; i++) {\n",
       "            var entry = entries[i];\n",
       "            var width, height;\n",
       "            if (entry.contentBoxSize) {\n",
       "                width = entry.contentBoxSize.inlineSize;\n",
       "                height = entry.contentBoxSize.blockSize;\n",
       "            } else {\n",
       "                width = entry.contentRect.width;\n",
       "                height = entry.contentRect.height;\n",
       "            }\n",
       "\n",
       "            // Keep the size of the canvas and rubber band canvas in sync with\n",
       "            // the canvas container.\n",
       "            canvas.setAttribute('width', width * mpl.ratio);\n",
       "            canvas.setAttribute('height', height * mpl.ratio);\n",
       "            canvas.setAttribute(\n",
       "                'style',\n",
       "                'width: ' + width + 'px; height: ' + height + 'px;'\n",
       "            );\n",
       "\n",
       "            rubberband_canvas.setAttribute('width', width);\n",
       "            rubberband_canvas.setAttribute('height', height);\n",
       "\n",
       "            // And update the size in Python. We ignore the initial 0/0 size\n",
       "            // that occurs as the element is placed into the DOM, which should\n",
       "            // otherwise not happen due to the minimum size styling.\n",
       "            if (width != 0 && height != 0) {\n",
       "                fig.request_resize(width, height);\n",
       "            }\n",
       "        }\n",
       "    });\n",
       "    resizeObserver.observe(canvas_div);\n",
       "\n",
       "    function on_mouse_event_closure(name) {\n",
       "        return function (event) {\n",
       "            return fig.mouse_event(event, name);\n",
       "        };\n",
       "    }\n",
       "\n",
       "    rubberband_canvas.addEventListener(\n",
       "        'mousedown',\n",
       "        on_mouse_event_closure('button_press')\n",
       "    );\n",
       "    rubberband_canvas.addEventListener(\n",
       "        'mouseup',\n",
       "        on_mouse_event_closure('button_release')\n",
       "    );\n",
       "    // Throttle sequential mouse events to 1 every 20ms.\n",
       "    rubberband_canvas.addEventListener(\n",
       "        'mousemove',\n",
       "        on_mouse_event_closure('motion_notify')\n",
       "    );\n",
       "\n",
       "    rubberband_canvas.addEventListener(\n",
       "        'mouseenter',\n",
       "        on_mouse_event_closure('figure_enter')\n",
       "    );\n",
       "    rubberband_canvas.addEventListener(\n",
       "        'mouseleave',\n",
       "        on_mouse_event_closure('figure_leave')\n",
       "    );\n",
       "\n",
       "    canvas_div.addEventListener('wheel', function (event) {\n",
       "        if (event.deltaY < 0) {\n",
       "            event.step = 1;\n",
       "        } else {\n",
       "            event.step = -1;\n",
       "        }\n",
       "        on_mouse_event_closure('scroll')(event);\n",
       "    });\n",
       "\n",
       "    canvas_div.appendChild(canvas);\n",
       "    canvas_div.appendChild(rubberband_canvas);\n",
       "\n",
       "    this.rubberband_context = rubberband_canvas.getContext('2d');\n",
       "    this.rubberband_context.strokeStyle = '#000000';\n",
       "\n",
       "    this._resize_canvas = function (width, height, forward) {\n",
       "        if (forward) {\n",
       "            canvas_div.style.width = width + 'px';\n",
       "            canvas_div.style.height = height + 'px';\n",
       "        }\n",
       "    };\n",
       "\n",
       "    // Disable right mouse context menu.\n",
       "    this.rubberband_canvas.addEventListener('contextmenu', function (_e) {\n",
       "        return false;\n",
       "    });\n",
       "\n",
       "    function set_focus() {\n",
       "        canvas.focus();\n",
       "        canvas_div.focus();\n",
       "    }\n",
       "\n",
       "    window.setTimeout(set_focus, 100);\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._init_toolbar = function () {\n",
       "    var fig = this;\n",
       "\n",
       "    var toolbar = document.createElement('div');\n",
       "    toolbar.classList = 'mpl-toolbar';\n",
       "    this.root.appendChild(toolbar);\n",
       "\n",
       "    function on_click_closure(name) {\n",
       "        return function (_event) {\n",
       "            return fig.toolbar_button_onclick(name);\n",
       "        };\n",
       "    }\n",
       "\n",
       "    function on_mouseover_closure(tooltip) {\n",
       "        return function (event) {\n",
       "            if (!event.currentTarget.disabled) {\n",
       "                return fig.toolbar_button_onmouseover(tooltip);\n",
       "            }\n",
       "        };\n",
       "    }\n",
       "\n",
       "    fig.buttons = {};\n",
       "    var buttonGroup = document.createElement('div');\n",
       "    buttonGroup.classList = 'mpl-button-group';\n",
       "    for (var toolbar_ind in mpl.toolbar_items) {\n",
       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
       "\n",
       "        if (!name) {\n",
       "            /* Instead of a spacer, we start a new button group. */\n",
       "            if (buttonGroup.hasChildNodes()) {\n",
       "                toolbar.appendChild(buttonGroup);\n",
       "            }\n",
       "            buttonGroup = document.createElement('div');\n",
       "            buttonGroup.classList = 'mpl-button-group';\n",
       "            continue;\n",
       "        }\n",
       "\n",
       "        var button = (fig.buttons[name] = document.createElement('button'));\n",
       "        button.classList = 'mpl-widget';\n",
       "        button.setAttribute('role', 'button');\n",
       "        button.setAttribute('aria-disabled', 'false');\n",
       "        button.addEventListener('click', on_click_closure(method_name));\n",
       "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
       "\n",
       "        var icon_img = document.createElement('img');\n",
       "        icon_img.src = '_images/' + image + '.png';\n",
       "        icon_img.srcset = '_images/' + image + '_large.png 2x';\n",
       "        icon_img.alt = tooltip;\n",
       "        button.appendChild(icon_img);\n",
       "\n",
       "        buttonGroup.appendChild(button);\n",
       "    }\n",
       "\n",
       "    if (buttonGroup.hasChildNodes()) {\n",
       "        toolbar.appendChild(buttonGroup);\n",
       "    }\n",
       "\n",
       "    var fmt_picker = document.createElement('select');\n",
       "    fmt_picker.classList = 'mpl-widget';\n",
       "    toolbar.appendChild(fmt_picker);\n",
       "    this.format_dropdown = fmt_picker;\n",
       "\n",
       "    for (var ind in mpl.extensions) {\n",
       "        var fmt = mpl.extensions[ind];\n",
       "        var option = document.createElement('option');\n",
       "        option.selected = fmt === mpl.default_extension;\n",
       "        option.innerHTML = fmt;\n",
       "        fmt_picker.appendChild(option);\n",
       "    }\n",
       "\n",
       "    var status_bar = document.createElement('span');\n",
       "    status_bar.classList = 'mpl-message';\n",
       "    toolbar.appendChild(status_bar);\n",
       "    this.message = status_bar;\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.request_resize = function (x_pixels, y_pixels) {\n",
       "    // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
       "    // which will in turn request a refresh of the image.\n",
       "    this.send_message('resize', { width: x_pixels, height: y_pixels });\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.send_message = function (type, properties) {\n",
       "    properties['type'] = type;\n",
       "    properties['figure_id'] = this.id;\n",
       "    this.ws.send(JSON.stringify(properties));\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.send_draw_message = function () {\n",
       "    if (!this.waiting) {\n",
       "        this.waiting = true;\n",
       "        this.ws.send(JSON.stringify({ type: 'draw', figure_id: this.id }));\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
       "    var format_dropdown = fig.format_dropdown;\n",
       "    var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
       "    fig.ondownload(fig, format);\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_resize = function (fig, msg) {\n",
       "    var size = msg['size'];\n",
       "    if (size[0] !== fig.canvas.width || size[1] !== fig.canvas.height) {\n",
       "        fig._resize_canvas(size[0], size[1], msg['forward']);\n",
       "        fig.send_message('refresh', {});\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_rubberband = function (fig, msg) {\n",
       "    var x0 = msg['x0'] / mpl.ratio;\n",
       "    var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
       "    var x1 = msg['x1'] / mpl.ratio;\n",
       "    var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
       "    x0 = Math.floor(x0) + 0.5;\n",
       "    y0 = Math.floor(y0) + 0.5;\n",
       "    x1 = Math.floor(x1) + 0.5;\n",
       "    y1 = Math.floor(y1) + 0.5;\n",
       "    var min_x = Math.min(x0, x1);\n",
       "    var min_y = Math.min(y0, y1);\n",
       "    var width = Math.abs(x1 - x0);\n",
       "    var height = Math.abs(y1 - y0);\n",
       "\n",
       "    fig.rubberband_context.clearRect(\n",
       "        0,\n",
       "        0,\n",
       "        fig.canvas.width / mpl.ratio,\n",
       "        fig.canvas.height / mpl.ratio\n",
       "    );\n",
       "\n",
       "    fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_figure_label = function (fig, msg) {\n",
       "    // Updates the figure title.\n",
       "    fig.header.textContent = msg['label'];\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_cursor = function (fig, msg) {\n",
       "    var cursor = msg['cursor'];\n",
       "    switch (cursor) {\n",
       "        case 0:\n",
       "            cursor = 'pointer';\n",
       "            break;\n",
       "        case 1:\n",
       "            cursor = 'default';\n",
       "            break;\n",
       "        case 2:\n",
       "            cursor = 'crosshair';\n",
       "            break;\n",
       "        case 3:\n",
       "            cursor = 'move';\n",
       "            break;\n",
       "    }\n",
       "    fig.rubberband_canvas.style.cursor = cursor;\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_message = function (fig, msg) {\n",
       "    fig.message.textContent = msg['message'];\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_draw = function (fig, _msg) {\n",
       "    // Request the server to send over a new figure.\n",
       "    fig.send_draw_message();\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_image_mode = function (fig, msg) {\n",
       "    fig.image_mode = msg['mode'];\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_history_buttons = function (fig, msg) {\n",
       "    for (var key in msg) {\n",
       "        if (!(key in fig.buttons)) {\n",
       "            continue;\n",
       "        }\n",
       "        fig.buttons[key].disabled = !msg[key];\n",
       "        fig.buttons[key].setAttribute('aria-disabled', !msg[key]);\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_navigate_mode = function (fig, msg) {\n",
       "    if (msg['mode'] === 'PAN') {\n",
       "        fig.buttons['Pan'].classList.add('active');\n",
       "        fig.buttons['Zoom'].classList.remove('active');\n",
       "    } else if (msg['mode'] === 'ZOOM') {\n",
       "        fig.buttons['Pan'].classList.remove('active');\n",
       "        fig.buttons['Zoom'].classList.add('active');\n",
       "    } else {\n",
       "        fig.buttons['Pan'].classList.remove('active');\n",
       "        fig.buttons['Zoom'].classList.remove('active');\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.updated_canvas_event = function () {\n",
       "    // Called whenever the canvas gets updated.\n",
       "    this.send_message('ack', {});\n",
       "};\n",
       "\n",
       "// A function to construct a web socket function for onmessage handling.\n",
       "// Called in the figure constructor.\n",
       "mpl.figure.prototype._make_on_message_function = function (fig) {\n",
       "    return function socket_on_message(evt) {\n",
       "        if (evt.data instanceof Blob) {\n",
       "            /* FIXME: We get \"Resource interpreted as Image but\n",
       "             * transferred with MIME type text/plain:\" errors on\n",
       "             * Chrome.  But how to set the MIME type?  It doesn't seem\n",
       "             * to be part of the websocket stream */\n",
       "            evt.data.type = 'image/png';\n",
       "\n",
       "            /* Free the memory for the previous frames */\n",
       "            if (fig.imageObj.src) {\n",
       "                (window.URL || window.webkitURL).revokeObjectURL(\n",
       "                    fig.imageObj.src\n",
       "                );\n",
       "            }\n",
       "\n",
       "            fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
       "                evt.data\n",
       "            );\n",
       "            fig.updated_canvas_event();\n",
       "            fig.waiting = false;\n",
       "            return;\n",
       "        } else if (\n",
       "            typeof evt.data === 'string' &&\n",
       "            evt.data.slice(0, 21) === 'data:image/png;base64'\n",
       "        ) {\n",
       "            fig.imageObj.src = evt.data;\n",
       "            fig.updated_canvas_event();\n",
       "            fig.waiting = false;\n",
       "            return;\n",
       "        }\n",
       "\n",
       "        var msg = JSON.parse(evt.data);\n",
       "        var msg_type = msg['type'];\n",
       "\n",
       "        // Call the  \"handle_{type}\" callback, which takes\n",
       "        // the figure and JSON message as its only arguments.\n",
       "        try {\n",
       "            var callback = fig['handle_' + msg_type];\n",
       "        } catch (e) {\n",
       "            console.log(\n",
       "                \"No handler for the '\" + msg_type + \"' message type: \",\n",
       "                msg\n",
       "            );\n",
       "            return;\n",
       "        }\n",
       "\n",
       "        if (callback) {\n",
       "            try {\n",
       "                // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
       "                callback(fig, msg);\n",
       "            } catch (e) {\n",
       "                console.log(\n",
       "                    \"Exception inside the 'handler_\" + msg_type + \"' callback:\",\n",
       "                    e,\n",
       "                    e.stack,\n",
       "                    msg\n",
       "                );\n",
       "            }\n",
       "        }\n",
       "    };\n",
       "};\n",
       "\n",
       "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
       "mpl.findpos = function (e) {\n",
       "    //this section is from http://www.quirksmode.org/js/events_properties.html\n",
       "    var targ;\n",
       "    if (!e) {\n",
       "        e = window.event;\n",
       "    }\n",
       "    if (e.target) {\n",
       "        targ = e.target;\n",
       "    } else if (e.srcElement) {\n",
       "        targ = e.srcElement;\n",
       "    }\n",
       "    if (targ.nodeType === 3) {\n",
       "        // defeat Safari bug\n",
       "        targ = targ.parentNode;\n",
       "    }\n",
       "\n",
       "    // pageX,Y are the mouse positions relative to the document\n",
       "    var boundingRect = targ.getBoundingClientRect();\n",
       "    var x = e.pageX - (boundingRect.left + document.body.scrollLeft);\n",
       "    var y = e.pageY - (boundingRect.top + document.body.scrollTop);\n",
       "\n",
       "    return { x: x, y: y };\n",
       "};\n",
       "\n",
       "/*\n",
       " * return a copy of an object with only non-object keys\n",
       " * we need this to avoid circular references\n",
       " * http://stackoverflow.com/a/24161582/3208463\n",
       " */\n",
       "function simpleKeys(original) {\n",
       "    return Object.keys(original).reduce(function (obj, key) {\n",
       "        if (typeof original[key] !== 'object') {\n",
       "            obj[key] = original[key];\n",
       "        }\n",
       "        return obj;\n",
       "    }, {});\n",
       "}\n",
       "\n",
       "mpl.figure.prototype.mouse_event = function (event, name) {\n",
       "    var canvas_pos = mpl.findpos(event);\n",
       "\n",
       "    if (name === 'button_press') {\n",
       "        this.canvas.focus();\n",
       "        this.canvas_div.focus();\n",
       "    }\n",
       "\n",
       "    var x = canvas_pos.x * mpl.ratio;\n",
       "    var y = canvas_pos.y * mpl.ratio;\n",
       "\n",
       "    this.send_message(name, {\n",
       "        x: x,\n",
       "        y: y,\n",
       "        button: event.button,\n",
       "        step: event.step,\n",
       "        guiEvent: simpleKeys(event),\n",
       "    });\n",
       "\n",
       "    /* This prevents the web browser from automatically changing to\n",
       "     * the text insertion cursor when the button is pressed.  We want\n",
       "     * to control all of the cursor setting manually through the\n",
       "     * 'cursor' event from matplotlib */\n",
       "    event.preventDefault();\n",
       "    return false;\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._key_event_extra = function (_event, _name) {\n",
       "    // Handle any extra behaviour associated with a key event\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.key_event = function (event, name) {\n",
       "    // Prevent repeat events\n",
       "    if (name === 'key_press') {\n",
       "        if (event.which === this._key) {\n",
       "            return;\n",
       "        } else {\n",
       "            this._key = event.which;\n",
       "        }\n",
       "    }\n",
       "    if (name === 'key_release') {\n",
       "        this._key = null;\n",
       "    }\n",
       "\n",
       "    var value = '';\n",
       "    if (event.ctrlKey && event.which !== 17) {\n",
       "        value += 'ctrl+';\n",
       "    }\n",
       "    if (event.altKey && event.which !== 18) {\n",
       "        value += 'alt+';\n",
       "    }\n",
       "    if (event.shiftKey && event.which !== 16) {\n",
       "        value += 'shift+';\n",
       "    }\n",
       "\n",
       "    value += 'k';\n",
       "    value += event.which.toString();\n",
       "\n",
       "    this._key_event_extra(event, name);\n",
       "\n",
       "    this.send_message(name, { key: value, guiEvent: simpleKeys(event) });\n",
       "    return false;\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.toolbar_button_onclick = function (name) {\n",
       "    if (name === 'download') {\n",
       "        this.handle_save(this, null);\n",
       "    } else {\n",
       "        this.send_message('toolbar_button', { name: name });\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.toolbar_button_onmouseover = function (tooltip) {\n",
       "    this.message.textContent = tooltip;\n",
       "};\n",
       "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Left button pans, Right button zooms\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\\nx/y fixes axis, CTRL fixes aspect\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
       "\n",
       "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
       "\n",
       "mpl.default_extension = \"png\";/* global mpl */\n",
       "\n",
       "var comm_websocket_adapter = function (comm) {\n",
       "    // Create a \"websocket\"-like object which calls the given IPython comm\n",
       "    // object with the appropriate methods. Currently this is a non binary\n",
       "    // socket, so there is still some room for performance tuning.\n",
       "    var ws = {};\n",
       "\n",
       "    ws.close = function () {\n",
       "        comm.close();\n",
       "    };\n",
       "    ws.send = function (m) {\n",
       "        //console.log('sending', m);\n",
       "        comm.send(m);\n",
       "    };\n",
       "    // Register the callback with on_msg.\n",
       "    comm.on_msg(function (msg) {\n",
       "        //console.log('receiving', msg['content']['data'], msg);\n",
       "        // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
       "        ws.onmessage(msg['content']['data']);\n",
       "    });\n",
       "    return ws;\n",
       "};\n",
       "\n",
       "mpl.mpl_figure_comm = function (comm, msg) {\n",
       "    // This is the function which gets called when the mpl process\n",
       "    // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
       "\n",
       "    var id = msg.content.data.id;\n",
       "    // Get hold of the div created by the display call when the Comm\n",
       "    // socket was opened in Python.\n",
       "    var element = document.getElementById(id);\n",
       "    var ws_proxy = comm_websocket_adapter(comm);\n",
       "\n",
       "    function ondownload(figure, _format) {\n",
       "        window.open(figure.canvas.toDataURL());\n",
       "    }\n",
       "\n",
       "    var fig = new mpl.figure(id, ws_proxy, ondownload, element);\n",
       "\n",
       "    // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
       "    // web socket which is closed, not our websocket->open comm proxy.\n",
       "    ws_proxy.onopen();\n",
       "\n",
       "    fig.parent_element = element;\n",
       "    fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
       "    if (!fig.cell_info) {\n",
       "        console.error('Failed to find cell for figure', id, fig);\n",
       "        return;\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_close = function (fig, msg) {\n",
       "    var width = fig.canvas.width / mpl.ratio;\n",
       "    fig.root.removeEventListener('remove', this._remove_fig_handler);\n",
       "\n",
       "    // Update the output cell to use the data from the current canvas.\n",
       "    fig.push_to_output();\n",
       "    var dataURL = fig.canvas.toDataURL();\n",
       "    // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
       "    // the notebook keyboard shortcuts fail.\n",
       "    IPython.keyboard_manager.enable();\n",
       "    fig.parent_element.innerHTML =\n",
       "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
       "    fig.close_ws(fig, msg);\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.close_ws = function (fig, msg) {\n",
       "    fig.send_message('closing', msg);\n",
       "    // fig.ws.close()\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.push_to_output = function (_remove_interactive) {\n",
       "    // Turn the data on the canvas into data in the output cell.\n",
       "    var width = this.canvas.width / mpl.ratio;\n",
       "    var dataURL = this.canvas.toDataURL();\n",
       "    this.cell_info[1]['text/html'] =\n",
       "        '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.updated_canvas_event = function () {\n",
       "    // Tell IPython that the notebook contents must change.\n",
       "    IPython.notebook.set_dirty(true);\n",
       "    this.send_message('ack', {});\n",
       "    var fig = this;\n",
       "    // Wait a second, then push the new image to the DOM so\n",
       "    // that it is saved nicely (might be nice to debounce this).\n",
       "    setTimeout(function () {\n",
       "        fig.push_to_output();\n",
       "    }, 1000);\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._init_toolbar = function () {\n",
       "    var fig = this;\n",
       "\n",
       "    var toolbar = document.createElement('div');\n",
       "    toolbar.classList = 'btn-toolbar';\n",
       "    this.root.appendChild(toolbar);\n",
       "\n",
       "    function on_click_closure(name) {\n",
       "        return function (_event) {\n",
       "            return fig.toolbar_button_onclick(name);\n",
       "        };\n",
       "    }\n",
       "\n",
       "    function on_mouseover_closure(tooltip) {\n",
       "        return function (event) {\n",
       "            if (!event.currentTarget.disabled) {\n",
       "                return fig.toolbar_button_onmouseover(tooltip);\n",
       "            }\n",
       "        };\n",
       "    }\n",
       "\n",
       "    fig.buttons = {};\n",
       "    var buttonGroup = document.createElement('div');\n",
       "    buttonGroup.classList = 'btn-group';\n",
       "    var button;\n",
       "    for (var toolbar_ind in mpl.toolbar_items) {\n",
       "        var name = mpl.toolbar_items[toolbar_ind][0];\n",
       "        var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
       "        var image = mpl.toolbar_items[toolbar_ind][2];\n",
       "        var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
       "\n",
       "        if (!name) {\n",
       "            /* Instead of a spacer, we start a new button group. */\n",
       "            if (buttonGroup.hasChildNodes()) {\n",
       "                toolbar.appendChild(buttonGroup);\n",
       "            }\n",
       "            buttonGroup = document.createElement('div');\n",
       "            buttonGroup.classList = 'btn-group';\n",
       "            continue;\n",
       "        }\n",
       "\n",
       "        button = fig.buttons[name] = document.createElement('button');\n",
       "        button.classList = 'btn btn-default';\n",
       "        button.href = '#';\n",
       "        button.title = name;\n",
       "        button.innerHTML = '<i class=\"fa ' + image + ' fa-lg\"></i>';\n",
       "        button.addEventListener('click', on_click_closure(method_name));\n",
       "        button.addEventListener('mouseover', on_mouseover_closure(tooltip));\n",
       "        buttonGroup.appendChild(button);\n",
       "    }\n",
       "\n",
       "    if (buttonGroup.hasChildNodes()) {\n",
       "        toolbar.appendChild(buttonGroup);\n",
       "    }\n",
       "\n",
       "    // Add the status bar.\n",
       "    var status_bar = document.createElement('span');\n",
       "    status_bar.classList = 'mpl-message pull-right';\n",
       "    toolbar.appendChild(status_bar);\n",
       "    this.message = status_bar;\n",
       "\n",
       "    // Add the close button to the window.\n",
       "    var buttongrp = document.createElement('div');\n",
       "    buttongrp.classList = 'btn-group inline pull-right';\n",
       "    button = document.createElement('button');\n",
       "    button.classList = 'btn btn-mini btn-primary';\n",
       "    button.href = '#';\n",
       "    button.title = 'Stop Interaction';\n",
       "    button.innerHTML = '<i class=\"fa fa-power-off icon-remove icon-large\"></i>';\n",
       "    button.addEventListener('click', function (_evt) {\n",
       "        fig.handle_close(fig, {});\n",
       "    });\n",
       "    button.addEventListener(\n",
       "        'mouseover',\n",
       "        on_mouseover_closure('Stop Interaction')\n",
       "    );\n",
       "    buttongrp.appendChild(button);\n",
       "    var titlebar = this.root.querySelector('.ui-dialog-titlebar');\n",
       "    titlebar.insertBefore(buttongrp, titlebar.firstChild);\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._remove_fig_handler = function () {\n",
       "    this.close_ws(this, {});\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._root_extra_style = function (el) {\n",
       "    el.style.boxSizing = 'content-box'; // override notebook setting of border-box.\n",
       "    el.addEventListener('remove', this._remove_fig_handler);\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._canvas_extra_style = function (el) {\n",
       "    // this is important to make the div 'focusable\n",
       "    el.setAttribute('tabindex', 0);\n",
       "    // reach out to IPython and tell the keyboard manager to turn it's self\n",
       "    // off when our div gets focus\n",
       "\n",
       "    // location in version 3\n",
       "    if (IPython.notebook.keyboard_manager) {\n",
       "        IPython.notebook.keyboard_manager.register_events(el);\n",
       "    } else {\n",
       "        // location in version 2\n",
       "        IPython.keyboard_manager.register_events(el);\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype._key_event_extra = function (event, _name) {\n",
       "    var manager = IPython.notebook.keyboard_manager;\n",
       "    if (!manager) {\n",
       "        manager = IPython.keyboard_manager;\n",
       "    }\n",
       "\n",
       "    // Check for shift+enter\n",
       "    if (event.shiftKey && event.which === 13) {\n",
       "        this.canvas_div.blur();\n",
       "        // select the cell after this one\n",
       "        var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
       "        IPython.notebook.select(index + 1);\n",
       "    }\n",
       "};\n",
       "\n",
       "mpl.figure.prototype.handle_save = function (fig, _msg) {\n",
       "    fig.ondownload(fig, null);\n",
       "};\n",
       "\n",
       "mpl.find_output_cell = function (html_output) {\n",
       "    // Return the cell and output element which can be found *uniquely* in the notebook.\n",
       "    // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
       "    // IPython event is triggered only after the cells have been serialised, which for\n",
       "    // our purposes (turning an active figure into a static one), is too late.\n",
       "    var cells = IPython.notebook.get_cells();\n",
       "    var ncells = cells.length;\n",
       "    for (var i = 0; i < ncells; i++) {\n",
       "        var cell = cells[i];\n",
       "        if (cell.cell_type === 'code') {\n",
       "            for (var j = 0; j < cell.output_area.outputs.length; j++) {\n",
       "                var data = cell.output_area.outputs[j];\n",
       "                if (data.data) {\n",
       "                    // IPython >= 3 moved mimebundle to data attribute of output\n",
       "                    data = data.data;\n",
       "                }\n",
       "                if (data['text/html'] === html_output) {\n",
       "                    return [cell, data, j];\n",
       "                }\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "};\n",
       "\n",
       "// Register the function which deals with the matplotlib target/channel.\n",
       "// The kernel may be null if the page has been refreshed.\n",
       "if (IPython.notebook.kernel !== null) {\n",
       "    IPython.notebook.kernel.comm_manager.register_target(\n",
       "        'matplotlib',\n",
       "        mpl.mpl_figure_comm\n",
       "    );\n",
       "}\n"
      ],
      "text/plain": [
       "<IPython.core.display.Javascript object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<img src=\"\" width=\"1000\">"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from loss import inverse_model, direct_model\n",
    "from data import domain, u_fn\n",
    "import jax.numpy as jnp\n",
    "import numpy as np\n",
    "\n",
    "inverse_params = agent.params[1]\n",
    "x_test = jnp.linspace(*domain[:, 0], 100).reshape((-1, 1))\n",
    "a_fn = lambda x: 1+jnp.exp(-(x-0.5)**2)\n",
    "a_pred = inverse_model(inverse_params, x_test)\n",
    "a_true = a_fn(x_test)\n",
    "\n",
    "direct_params = agent.params[0]\n",
    "u_pred = direct_model(direct_params, x_test)\n",
    "u_true = u_fn(x_test)\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib notebook\n",
    "\n",
    "f, ax = plt.subplots(1, 2, figsize = (10, 5))\n",
    "ax[0].plot(x_test, a_pred, label = \"pred\")\n",
    "ax[0].plot(x_test, a_true, label = \"true\")\n",
    "ax[0].set_title(\"a\")\n",
    "ax[1].plot(x_test, u_pred, label = \"pred\")\n",
    "ax[1].plot(x_test, u_true, label = \"true\")\n",
    "ax[1].set_title(\"u\")\n",
    "for ax_ in ax:\n",
    "\tax_.legend()\n",
    "\tax_.grid()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
